package com.kaochong.xcx.service.impl;

import com.google.common.collect.Lists;

import com.kaochong.common.util.BeanConvertUtil;
import com.kaochong.xcx.cache.UserMistakesCache;
import com.kaochong.xcx.cache.WordCache;
import com.kaochong.xcx.enums.StageStatus;
import com.kaochong.xcx.entity.UserMistakes;
import com.kaochong.xcx.entity.WordBook;
import com.kaochong.xcx.entity.mistakes.UserMistakes10;
import com.kaochong.xcx.entity.mistakes.UserMistakes11;
import com.kaochong.xcx.entity.mistakes.UserMistakes12;
import com.kaochong.xcx.entity.mistakes.UserMistakes13;
import com.kaochong.xcx.entity.mistakes.UserMistakes14;
import com.kaochong.xcx.entity.mistakes.UserMistakes15;
import com.kaochong.xcx.entity.mistakes.UserMistakes16;
import com.kaochong.xcx.entity.mistakes.UserMistakes17;
import com.kaochong.xcx.entity.mistakes.UserMistakes8;
import com.kaochong.xcx.entity.mistakes.UserMistakes9;
import com.kaochong.xcx.pojo.cache.WordModel;
import com.kaochong.xcx.pojo.vo.ReviewWordVO;
import com.kaochong.xcx.dao.UserMistakes10Mapper;
import com.kaochong.xcx.dao.UserMistakes11Mapper;
import com.kaochong.xcx.dao.UserMistakes12Mapper;
import com.kaochong.xcx.dao.UserMistakes13Mapper;
import com.kaochong.xcx.dao.UserMistakes14Mapper;
import com.kaochong.xcx.dao.UserMistakes15Mapper;
import com.kaochong.xcx.dao.UserMistakes16Mapper;
import com.kaochong.xcx.dao.UserMistakes17Mapper;
import com.kaochong.xcx.dao.UserMistakes8Mapper;
import com.kaochong.xcx.dao.UserMistakes9Mapper;
import com.kaochong.xcx.dao.UserMistakesMapper;
import com.kaochong.xcx.service.UserMistakesService;
import com.kaochong.xcx.service.WordBookService;
import com.kaochong.xcx.utils.MixUtil;
import com.kaochong.xcx.web.aspect.CurrentUser;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author han
 * @date 2018-06-07 17:53
 */
@Service
public class UserMistakesServiceImpl implements UserMistakesService {
	
	@Autowired
	UserMistakesMapper userMistakesMapper;
	
	@Autowired
	UserMistakes8Mapper userMistakesMapper8;
	
	@Autowired
	UserMistakes9Mapper userMistakesMapper9;
	
	@Autowired
	UserMistakes10Mapper userMistakesMapper10;
	
	@Autowired
	UserMistakes11Mapper userMistakesMapper11;
	
	@Autowired
	UserMistakes12Mapper userMistakesMapper12;
	
	@Autowired
	UserMistakes13Mapper userMistakesMapper13;
	
	@Autowired
	UserMistakes14Mapper userMistakesMapper14;
	
	@Autowired
	UserMistakes15Mapper userMistakesMapper15;
	
	@Autowired
	UserMistakes16Mapper userMistakesMapper16;
	
	@Autowired
	UserMistakes17Mapper userMistakesMapper17;
	
	@Override
	public List<UserMistakes> findUserReviewMistakes(Long userId, String targetMarkId, Integer
			status, Integer errorTimes, Integer target) {
		List<UserMistakes> result = Lists.newArrayList();
		switch (target) {
			case 4:
			case 6:
			case 7:
				result = userMistakesMapper.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
						(userId, targetMarkId, status, errorTimes);
				break;
			case 8:
				List<UserMistakes8> mistakes8 =
						userMistakesMapper8.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
						(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes8, UserMistakes.class);
				break;
			case 9:
				List<UserMistakes9> mistakes9 =
						userMistakesMapper9.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
						(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes9, UserMistakes.class);
				break;
			case 10:
				List<UserMistakes10> mistakes10 =
						userMistakesMapper10.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes10, UserMistakes.class);
				break;
			case 11:
				List<UserMistakes11> mistakes11 =
						userMistakesMapper11.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes11, UserMistakes.class);
				break;
			case 12:
				List<UserMistakes12> mistakes12 =
						userMistakesMapper12.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes12, UserMistakes.class);
				break;
			case 13:
				List<UserMistakes13> mistakes13 =
						userMistakesMapper13.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes13, UserMistakes.class);
				break;
			case 14:
				List<UserMistakes14> mistakes14 =
						userMistakesMapper14.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes14, UserMistakes.class);
				break;
			case 15:
				List<UserMistakes15> mistakes15 =
						userMistakesMapper15.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes15, UserMistakes.class);
				break;
			case 16:
				List<UserMistakes16> mistakes16 =
						userMistakesMapper16.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes16, UserMistakes.class);
				break;
			case 17:
				List<UserMistakes17> mistakes17 =
						userMistakesMapper17.findByUserIdAndTargetMarkIdAndStatusAndErrorTimes
								(userId, targetMarkId, status, errorTimes);
				result = BeanConvertUtil.convert(mistakes17, UserMistakes.class);
				break;
			default:
				break;
		}
		return result;
	}
	
	@Override
	public List<UserMistakes> findBeforeTwoDayMistakes(Long userId, String targetMarkId, Integer
			status, Integer currStage, Integer errorTimes, Integer target) {
		List<UserMistakes> result = Lists.newArrayList();
		switch (target) {
			case 4:
			case 6:
			case 7:
				result = userMistakesMapper.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
						targetMarkId, status, currStage, errorTimes);
				break;
			case 8:
				List<UserMistakes8> mistakes8 =
						userMistakesMapper8.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes8, UserMistakes.class);
				break;
			case 9:
				List<UserMistakes9> mistakes9 =
						userMistakesMapper9.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
					targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes9, UserMistakes.class);
				break;
			case 10:
				List<UserMistakes10> mistakes10 =
						userMistakesMapper10.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes10, UserMistakes.class);
				break;
			case 11:
				List<UserMistakes11> mistakes11 =
						userMistakesMapper11.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes11, UserMistakes.class);
				break;
			case 12:
				List<UserMistakes12> mistakes12 =
						userMistakesMapper12.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes12, UserMistakes.class);
				break;
			case 13:
				List<UserMistakes13> mistakes13 =
						userMistakesMapper13.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes13, UserMistakes.class);
				break;
			case 14:
				List<UserMistakes14> mistakes14 =
						userMistakesMapper14.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes14, UserMistakes.class);
				break;
			case 15:
				List<UserMistakes15> mistakes15 =
						userMistakesMapper15.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes15, UserMistakes.class);
				break;
			case 16:
				List<UserMistakes16> mistakes16 =
						userMistakesMapper16.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes16, UserMistakes.class);
				break;
			case 17:
				List<UserMistakes17> mistakes17 =
						userMistakesMapper17.findByUserIdAndTargetMarkIdAndStatusAndStageLessThanAndErrorTimesLessThanEqual(userId,
								targetMarkId, status, currStage, errorTimes);
				result = BeanConvertUtil.convert(mistakes17, UserMistakes.class);
				break;
			default:
				break;
		}
		return result;
	}
	
	@Override
	public List<UserMistakes> findAllMistakes(Long userId, String targetMarkId, Integer target) {
		List<UserMistakes> result = Lists.newArrayList();
		switch (target) {
			case 4:
			case 6:
			case 7:
				result = userMistakesMapper.findByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 8:
				List<UserMistakes8> mistakes8 =
						userMistakesMapper8.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes8, UserMistakes.class);
				break;
			case 9:
				List<UserMistakes9> mistakes9 =
						userMistakesMapper9.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes9, UserMistakes.class);
				break;
			case 10:
				List<UserMistakes10> mistakes10 =
						userMistakesMapper10.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes10, UserMistakes.class);
				break;
			case 11:
				List<UserMistakes11> mistakes11 =
						userMistakesMapper11.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes11, UserMistakes.class);
				break;
			case 12:
				List<UserMistakes12> mistakes12 =
						userMistakesMapper12.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes12, UserMistakes.class);
				break;
			case 13:
				List<UserMistakes13> mistakes13 =
						userMistakesMapper13.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes13, UserMistakes.class);
				break;
			case 14:
				List<UserMistakes14> mistakes14 =
						userMistakesMapper14.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes14, UserMistakes.class);
				break;
			case 15:
				List<UserMistakes15> mistakes15 =
						userMistakesMapper15.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes15, UserMistakes.class);
				break;
			case 16:
				List<UserMistakes16> mistakes16 =
						userMistakesMapper16.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes16, UserMistakes.class);
				break;
			case 17:
				List<UserMistakes17> mistakes17 =
						userMistakesMapper17.findByUserIdAndTargetMarkId(userId, targetMarkId);
				result = BeanConvertUtil.convert(mistakes17, UserMistakes.class);
				break;
			default:
				break;
		}
		return result;
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Integer deleteUserMistakes(Long userId, String targetMarkId, Integer target) {
//		return userMistakesRepository.deleteUserMistakes(userId, targetMarkId);
		Integer result = 0;
		switch (target) {
			case 4:
			case 6:
			case 7:
				result = userMistakesMapper.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 8:
				result = userMistakesMapper8.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 9:
				result = userMistakesMapper9.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 10:
				result = userMistakesMapper10.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 11:
				result = userMistakesMapper11.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 12:
				result = userMistakesMapper12.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 13:
				result = userMistakesMapper13.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 14:
				result = userMistakesMapper14.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 15:
				result = userMistakesMapper15.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 16:
				result = userMistakesMapper16.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			case 17:
				result = userMistakesMapper17.deleteByUserIdAndTargetMarkId(userId, targetMarkId);
				break;
			default:
				break;
		}
		return result;
	}
	
	@Override
	public void save(List<UserMistakes> mistakesAll, Integer target) {
		switch (target) {
			case 4:
			case 6:
			case 7:
				userMistakesMapper.save(mistakesAll);
				break;
			case 8:
				List<UserMistakes8> mistakes8 = BeanConvertUtil.convert(mistakesAll, UserMistakes8.class);
				userMistakesMapper8.save(mistakes8);
				break;
			case 9:
				List<UserMistakes9> mistakes9 = BeanConvertUtil.convert(mistakesAll, UserMistakes9.class);
				userMistakesMapper9.save(mistakes9);
				break;
			case 10:
				List<UserMistakes10> mistakes10 = BeanConvertUtil.convert(mistakesAll, UserMistakes10.class);
				userMistakesMapper10.save(mistakes10);
				break;
			case 11:
				List<UserMistakes11> mistakes11 = BeanConvertUtil.convert(mistakesAll, UserMistakes11.class);
				userMistakesMapper11.save(mistakes11);
				break;
			case 12:
				List<UserMistakes12> mistakes12 = BeanConvertUtil.convert(mistakesAll, UserMistakes12.class);
				userMistakesMapper12.save(mistakes12);
				break;
			case 13:
				List<UserMistakes13> mistakes13 = BeanConvertUtil.convert(mistakesAll, UserMistakes13.class);
				userMistakesMapper13.save(mistakes13);
				break;
			case 14:
				List<UserMistakes14> mistakes14 = BeanConvertUtil.convert(mistakesAll, UserMistakes14.class);
				userMistakesMapper14.save(mistakes14);
				break;
			case 15:
				List<UserMistakes15> mistakes15 = BeanConvertUtil.convert(mistakesAll, UserMistakes15.class);
				userMistakesMapper15.save(mistakes15);
				break;
			case 16:
				List<UserMistakes16> mistakes16 = BeanConvertUtil.convert(mistakesAll, UserMistakes16.class);
				userMistakesMapper16.save(mistakes16);
				break;
			case 17:
				List<UserMistakes17> mistakes17 = BeanConvertUtil.convert(mistakesAll, UserMistakes17.class);
				userMistakesMapper17.save(mistakes17);
				break;
			default:
				break;
		}
	}
	
	@Autowired
	WordBookService wordBookService;
	
	@Autowired
	WordCache wordCache;
	
	@Autowired
	UserMistakesCache userMistakesCache;
	
	@Autowired
	MixUtil mixUtil;
	
	@Override
	public List<ReviewWordVO> reviewMistakes(CurrentUser user, Integer stage) {
		List<ReviewWordVO> listVO = Lists.newArrayList();
		
		Integer target = user.getTarget();
		Long userId = user.getId();
		String mark = user.getTargetMarkId();
		Integer currStage = user.getCurrStage();
		Integer currStageStatus = user.getCurrStageStatus();
		
		WordBook wordBook = wordBookService.getWordBook(target);
		Integer maxStudyStage = wordBook.getTotalStage() - wordBook.getReview();
		
		if (stage > currStage) {
			stage = currStage;
		}
		
		if (stage > maxStudyStage) {
			stage = maxStudyStage;
		} else {
			if (currStage == stage && !StageStatus.FINISHED.getCode().equals(currStageStatus)) {
				stage = stage - 1 == 0 ? 0 : stage - 1;
			}
		}
		List<WordModel> stageWord = wordCache.getStageWord(target, stage);
		Map<String, Object> map = mixUtil.mixUp(stageWord, target);
		
		List<WordModel> wordList = (List<WordModel>) map.get("wordList");
		List<UserMistakes> mistakes = userMistakesCache.hGetAll(userId, mark);
		if (mistakes.isEmpty()) {
			mistakes = findAllMistakes(userId, mark, target);
		}
		
		listVO = BeanConvertUtil.convert(wordList, ReviewWordVO.class);
		
		for (UserMistakes mistake : mistakes) {
			for (ReviewWordVO vo : listVO) {
				if (mistake.getWordId().equals(vo.getId())) {
					vo.setRightSign(false);
					break;
				}
			}
		}
		return listVO;
	}
	
	@Override
	public Integer reviewMistakesCount(CurrentUser user, Integer stage) {
		
		Integer target = user.getTarget();
		Long userId = user.getId();
		String mark = user.getTargetMarkId();
		Integer currStage = user.getCurrStage();
		Integer currStageStatus = user.getCurrStageStatus();
		
		WordBook wordBook = wordBookService.getWordBook(target);
		Integer maxStudyStage = wordBook.getTotalStage() - wordBook.getReview();
		
		if (stage > currStage) {
			stage = currStage;
		}
		
		if (stage > maxStudyStage) {
			stage = maxStudyStage;
		} else {
			if (currStage == stage && !StageStatus.FINISHED.getCode().equals(currStageStatus)) {
				stage = stage - 1 == 0 ? 0 : stage - 1;
			}
		}
		List<WordModel> stageWord = wordCache.getStageWord(target, stage);
		
		List<UserMistakes> mistakes = userMistakesCache.hGetAll(userId, mark);
		if (mistakes.isEmpty()) {
			mistakes = findAllMistakes(userId, mark, target);
		}
		
		int mistakesCount = 0;
		for (UserMistakes mistake : mistakes) {
			for (WordModel vo : stageWord) {
				if (mistake.getWordId().equals(vo.getId())) {
					mistakesCount++;
					break;
				}
			}
		}
		return mistakesCount;
	}
}
